<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Flow control in Ruby</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Ruby, learn Ruby, language, flow control, if, else, while, foreach">
<meta name="description" content="In this part of the Ruby tutorial, we cover flow control.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container2">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>


<div class="content2">

<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Flow control in Ruby</h1>

<p>
In this part of the Ruby tutorial, we will talk about the flow control.
We will define several keywords that enable us to control the flow of 
a Ruby program. 
</p>

<div class="big_hor">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* big_horizontal */
google_ad_slot = "2904953388";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<p>
Conditionals and loops alter the flow of a Ruby program. Conditionals
are keywords, that execute a certain statement under a specific condition.
Loops are blocks of program that are executed multiple times. 
When the program is run, the statements are executed from the top 
of the source file to the bottom. One by one. 
</p>


<h2>The if statement</h2>

<p>
The <code>if</code> keyword is used to check if an expression 
is true. If it is true, a statement is then executed. The statement can 
be a single statement or a compound statement. A compound statement 
consists of multiple statements enclosed by the block. A block is code
enclosed by the <code>end</code> keyword. The <code>then</code> keywords
is optional. 
</p>

<pre class="code">
#!/usr/bin/ruby

num = gets.to_i

if num > 0 then

    puts "num variable is positive"
    puts "num variable equals to #{num}"
end
</pre>

<p> 
We read a number from a user. If the number is greater than
zero, then we print two messages to the console. If not, nothing
is done.
</p>

<pre>
$ ./simpleif.rb 
4
num variable is positive
num variable equals to 4
</pre>

<p>
The condition is met and the message is written to the console. 
</p>


<hr class="btm">

<p>
We can use the <code>else</code> keyword to create a simple branch. 
If the expression inside the square brackets following 
the <code>if</code> keyword evaluates to false, the statement 
following the <code>else</code> keyword is automatically executed. 
The block of code is enclosed by the <code>end</code> keyword. 
</p>

<pre class="code">
#!/usr/bin/ruby

age = 17

if age > 18

    puts "Driving licence issued"
else

    puts "Driving licence not permitted"
end
</pre>

<p>
We have a age variable.  The boolean expression 
evaluates to false and we get "Driving licence not permitted" 
in the console.  
</p>

<pre>
$ ./licence.rb 
Driving licence not permitted
</pre>


<p>
We can create multiple branches using the <code>elseif</code> keyword.
The <code>elseif</code> keyword tests for another condition, if and only if 
the previous condition was not met. Note, that we can use multiple 
<code>elseif</code> keywords in our tests.
</p>

<pre class="code">
#!/usr/bin/ruby

print "Enter a number: "

num = gets.to_i

if num &lt; 0

    puts "#{num} is negative"
elsif num == 0

   puts "#{num} is zero"
elsif num > 0

   puts "#{num} is positive"
end
</pre>

<p>
We have a numerical variable and we test it, if it is a negative number or 
positive or if it equals to zero. Depending on the value read from the user,
we print one of the messages to the console. 
</p>

<h2>The case statement</h2>

<p>
The <code>case</code> statement is a selection control flow statement. 
It allows the value of a variable or expression to control the flow of program 
execution via a multi way branch. It creates multiple branches in a simpler way 
than using the combination of <code>if</code>, <code>elseif</code> 
statements.
</p>

<p>
We have a variable or an expression. The <code>case</code> keyword is used
to test a value from the variable or the expression against a list of values. 
The list of values is presented with the <code>when</code> keyword. 
If the values match, the statement following the <code>when</code> is executed. 
There is an optional <code>else</code> statement. It is executed, if no other 
match is found.
</p>

<pre class="code">
#!/usr/bin/ruby

print "Enter top level domain: "

domain = gets.chomp

case domain
    when "us"
        puts "United States"
    when "de" 
        puts "Germany"
    when "sk" 
        puts "Slovakia"
    when "hu" 
        puts "Hungary"
    else
        puts "Unknown"
end
</pre>

<p>
In our program, we have a domain variable. We read a value for the variable
from the command line. We use the <code>when</code> statement to 
test for the value of the variable. There are several options. If the value 
equals for example to "us" the "United States" string is printed to the console. 
</p>

<pre class="explanation">
domain = gets.chomp
</pre>

<p>
We get an input from the user with the <code>gets</code> method. 
The input also includes the newline character. The newline is excluded with the
<code>chomp</code> method.
</p>

<pre>
$ ./domains.rb 
Enter top level domain: hu
Hungary
</pre>

<p>
We have entered "hu" string to the console and the program responded with "Hungary".
</p>


<h2>The while, until statements</h2>

<p>
The <code>while</code> statement is a control flow statement 
that allows code to be executed repeatedly based on a given boolean condition. 
It executes the code while the condition is true. 
</p>


<p>
The <code>while</code> keyword executes the statements inside the
block enclosed by the <code>end</code> keyword. The statements are executed each time 
the expression is evaluated to true. 
</p>

<pre class="code">
#!/usr/bin/ruby

i = 0
sum = 0

while i &lt; 10  do
   i = i + 1
   sum = sum + i
end

puts "The sum of 0..9 values is #{sum}"
</pre>

<p>
In the code example, we calculate the sum of values from a range of numbers.
</p>

<p>
The <code>while</code> loop has three parts. Initialization, testing and 
updating. Each execution of the statement is called a cycle. 
</p>

<pre class="explanation">
i = 0
sum = 0
</pre>

<p>
We initiate the i and the sum variables. The i is used as a counter.
</p>

<pre class="explanation">
while i &lt; 10  do
   ...
end
</pre>

<p>
The expression between the <code>while</code> and <code>do</code> keywords
is the second phase, the testing. Note that the <code>do</code> keyword is 
optional. The statements in the body are executed, until the expression is evaluated to false. 
</p>

<pre class="explanation">
i = i + 1
</pre>

<p>
The last, third phase of the <code>while</code> loop. The updating. We increment
the counter. Note that improper handling of the <code>while</code> loops may lead
to endless cycles. 
</p>

<pre>
$ ./while.rb 
The sum of 0..9 values is 55
</pre>

<p>
Output of the example. 
</p>

<hr class="btm">

<p>
The <code>until</code> is a control flow statement, which executes code
while the condition is false. The loop stops, when the condition is
true. 
</p>

<pre class="code">
#!/usr/bin/ruby

hours_left = 12

until hours_left == 0
    
    if hours_left == 1
        puts "There is #{hours_left} hour left"
    else
        puts "There are #{hours_left} hours left"
    end

    hours_left -= 1
end
</pre>

<p>
In our example, we have a variable hours_left. We begin a count down. 
Each loop cycle, we print how many hours are left there. When the
variable equals zero, the loop is stopped. 
</p>

<pre>
$ ./until.rb 
There are 12 hours left
There are 11 hours left
There are 10 hours left
There are 9 hours left
There are 8 hours left
There are 7 hours left
There are 6 hours left
There are 5 hours left
There are 4 hours left
There are 3 hours left
There are 2 hours left
There is 1 hour left
</pre>

<p>
Running the example. 
</p>


<h2>The for statement</h2>

<p>
When the number of cycles is know before the loop is initiated, 
we can use the <code>for</code> statement. The for loop is used in
conjuction with ranges. For each element of a range a block of statements is 
executed. The statements are enclosed with the <code>end</code> keyword. 
The <code>do</code> keyword is optional. 
</p>


<pre class="code">
#!/usr/bin/ruby


for i in 0..9 do

    puts "#{i}"
end
</pre>

<p>
In this example, we print numbers 0..9 to the console. In each of the loops
the i variable holds a value from a range of numbers. The value is printed
to the console. The .. range operator creates a list of numbers, including the
last number. 
</p>

<pre>
$ ./forloop.rb 
0
1
2
3
4
5
6
7
8
9
</pre>

<p>
Output of the example. 
</p>

<hr class="btm">

<p>
To go through an array of elements using the for loop, we can use the <code>length</code>
method of the array. 
</p>

<pre class="code">
#!/usr/bin/ruby

planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter",
    "Saturn", "Uranus", "Neptune"]

for i in 0...planets.length

    puts planets[i]
end
</pre>

<p>
In this example, we have an array of planets. We traverse the array
and print each element of the array.
</p>

<pre class="explanation">
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter",
    "Saturn", "Uranus", "Neptune"]
</pre>

<p>
This is an array of planets. 
</p>

<pre class="explanation">
for i in 0...planets.length
</pre>

<p>
The <code>length</code> method returns the length of the array.
Since arrays begin with 0, the last index is n-1. The ... range operator
creates a range of numbers, excluding the last high value. 
</p>

<pre class="explanation">
puts planets[i]
</pre>

<p>
We print the element having a specific index in the array. 
</p>

<pre>
$ ./planets2.rb 
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
</pre>

<p>
Running the above Ruby program gives this output.
</p>

<h2>The each method</h2>

<p>
In Ruby, we can use the <code>each</code> method to iterate through
items of an array. It takes two parameters. An element and a block. 
The element is put within pipes. It is a placeholder for the item of the
current iteration. The block is the code which is executed on each iteration.
</p>

<pre class="code">
#!/usr/bin/ruby

planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter",
    "Saturn", "Uranus", "Neptune"]

planets.each do |planet| 

    puts planet
end
</pre>

<p>
In this example, we go through an array of planets using the 
<code>each</code> iterator.
</p>

<pre class="explanation">
planets.each do |planet| 

    puts planet
end
</pre>

<p>
The <code>each</code> iterator is a method, which works on the planets
array. The planet is a placeholder for a current item of the iteration.
We could put there any character we wanted. We could use {} characters instead
of do, end keywords. 
</p>


<h2>The break, next statements</h2>

<p>
The <code>break</code> statement can be used to terminate 
a block defined by <code>while</code>, <code>for</code>
or <code>case</code> statements.
</p>

<pre class="code">
#!/usr/bin/ruby

while true

    r = 1 + rand(30)
    print "#{r} "

    if r == 22
        break
    end
end

puts
</pre>

<p>
We define an endless <code>while</code> loop. We use the <code>break</code> 
statement to get out of this loop. We choose a random value from 1 to 30. 
We print the value. If the value equals to 22, we finish the endless while loop. 
</p>

<pre class="explanation">
while true
   ...
end
</pre>

<p>
This is an endless cycle. The condition for the while loop is always true. 
The only way to get out of this endless loop is to break out.
</p>

<pre class="explanation">
r = 1 + rand(30)
print "#{r} "
</pre>

<p>
We compute a random number from 1 to 30 and print it to the console. 
</p>

<pre class="explanation">
if r == 22
    break
end
</pre>

<p>
If the number equals to 22, we break the loop. The program finishes. 
</p>

<pre>
$ ./break.rb 
20 14 6 26 30 12 2 10 18 29 28 11 30 26 20 22 
</pre>

<p>
We might get something like this.
</p>

<hr class="btm">

<p>
The <code>next</code> statement is used to skip a
part of the loop and continue with the next iteration of the loop.
It can be used in combination with <code>for</code> and 
<code>while</code> statements. 
</p>

<p>
In the following example, we will print a list of numbers, 
that cannot be divided by 2 without a remainder. 
</p>

<pre class="code">
#!/usr/bin/ruby

num = 0

while num &lt; 100

    num += 1

    if (num % 2 == 0)
        next
    end

    print "#{num} " 
end    

puts
</pre>

<p>
We iterate through numbers 1..99 with the <code>while</code> loop.
</p>

<pre class="explanation">
if (num % 2 == 0)
    next
end
</pre>

<p>
If the expression num % 2 returns 0, the number in question can be divided by 2.
The <code>next</code> statement is executed and the rest of the cycle is skipped.
In our case, the last statement of the loop is skipped and the number is not 
printed to the console. The next iteration is started. 
</p>

<pre class="code">
$ ./next.rb 
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 
41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 
79 81 83 85 87 89 91 93 95 97 99 
</pre>

<p>
Output of the example. 
</p>

<h2>The redo statement</h2>

<p>
The <code>redo</code> statement restarts an iteration of a loop.
Without checking the loop condition. The last example will be a more complex one.
It will demonstrate the <code>redo</code> statement and other features as well. 
</p>


<pre class="code">
#!/usr/bin/ruby

options = ["rock", "scissors", "paper"]

while true

    print &lt;&lt;TEXT
1 - rock
2 - scissors
3 - paper
9 - end game
TEXT

    val = gets.to_i

    r = rand(3) + 1

    if val == 9 
        puts "End"
        exit
    end

    if ![1, 2, 3, 9].include?(val)
        puts "Invalid option"
        redo
    end

    computer = options[r-1]
    human = options[val-1]

    puts "I have #{computer}, you have #{human}"

    if val == r
        puts "Tie, next throw"
        redo
    end


    if val == 1 and r == 2
        puts "Rock blunts scissors, you win"

    elsif val == 2 and r == 1
        puts "Rock blunts scissors, you loose"

    elsif val == 2 and r == 3
        puts "Scissors cut paper, you win"

    elsif val == 3 and r == 2
        puts "Scissors cut paper, you loose"

    elsif val == 3 and r == 1
        puts "Paper covers rock, you win"

    elsif val == 1 and r == 3
        puts "Paper covers rock, you loose"

    end    
end
</pre>

<p>
We have a simple Rock, scissors and paper game. In this code example,
we will utilize the <code>redo</code> statement, conditionals, random numbers,
arrays and user input. 
</p>

<pre class="explanation">
options = ["rock", "scissors", "paper"]
</pre>

<p>
We have all possibilities of the game in the options array.
These three words will be used when printing messages to the console. 
</p>

<pre class="explanation">
    print &lt;&lt;TEXT
1 - rock
2 - scissors
3 - paper
9 - end game
TEXT
</pre>

<p>
We print the menu to the console using the heredoc syntax. The heredoc starts with &lt;&lt; 
followed by a string. The same string closes the construct; it must be left aligned. This allows us
to print multiple lines in one step. This menu is printed each game cycle. 
</p>

<pre class="explanation">
val = gets.to_i

r = rand(3) + 1
</pre>

<p>
In these code lines, we read a value from the terminal. Then we select randomly a number
among 1, 2, 3. Note that rand(3) returns a number from 0, 1, 2. This is why we add 1. 
</p>

<pre class="explanation">
if val == 9 
    puts "End"
    exit
end
</pre>

<p>
If the input from the user equals 9, we print 'End' to the terminal
and end the game. The <code>exit</code> method terminates the program.
</p>

<pre class="explanation">
if ![1, 2, 3, 9].include?(val)
    puts "Invalid option"
    redo
end
</pre>

<p>
In case the user selects a different value than offered in the menu, we inform
about the invalid option and redo the cycle. 
</p>

<pre class="explanation">
computer = options[r-1]
human = options[val-1]

puts "I have #{computer}, you have #{human}"
</pre>

<p>
The numbers are transformed into strings. We print both the user's and the
computer's selection. 
</p>

<pre class="explanation">
if val == r
    puts "Tie, next throw"
    redo
end
</pre>

<p>
If both parties have the same option, there is a tie. We start a new game 
cycle. We utilize the <code>redo</code> keyword. 
</p>

<pre class="explanation">
if val == 1 and r == 2
    puts "Rock blunts scissors, you win"

elsif val == 2 and r == 1
    puts "Rock blunts scissors, you loose"
...
</pre>

<p>
Using multiple <code>if</code>, <code>elsif</code> branches, we compare the selections of
the user and the computer. We decide, who is the winner. 
</p>

<pre>
$ ./redo.rb 
1 - rock
2 - scissors
3 - paper
9 - end game
3
I have paper, you have paper
Tie, next throw
1 - rock
2 - scissors
3 - paper
9 - end game
2
I have rock, you have scissors
Rock blunts scissors, you loose
1 - rock
2 - scissors
3 - paper
9 - end game
1
I have scissors, you have rock
Rock blunts scissors, you win
1 - rock
2 - scissors
3 - paper
9 - end game
9
End
</pre>

<p>
Sample output. 
</p>


<p>
In this part of the Ruby tutorial, we were talking about control 
flow structures. 
</p>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified December 14, 2011  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
